#include "CudaBuffer.h"

using namespace OBR;

CudaBuffer::CudaBuffer()
{
}
CudaBuffer::CudaBuffer(size_t size)
{
    this->resize(size);
}
CudaBuffer::CudaBuffer(const CudaBuffer &src)
{
    if (src.sizeInBytes > 0)
    {
        this->resize(src.sizeInBytes);
        CUDA_CHECK(cudaMemcpy(d_ptr, src.d_ptr, sizeInBytes, cudaMemcpyDeviceToDevice));
    }
}
CudaBuffer::~CudaBuffer()
{
    if (d_ptr)
        free();
}

void CudaBuffer::alloc(size_t size)
{
    assert(d_ptr == nullptr);
    this->sizeInBytes = size;
    CUDA_CHECK(cudaMalloc((void **)&d_ptr, sizeInBytes));
    CUDA_CHECK(cudaMemset((void *)d_ptr, 0, sizeInBytes));
}

void CudaBuffer::resize(size_t size)
{
    if (d_ptr)
        free();
    this->alloc(size);
}

void CudaBuffer::free()
{
    CUDA_CHECK(cudaFree(d_ptr));
    d_ptr = nullptr;
    sizeInBytes = 0;
}

void CudaBuffer::upload(const void *t, size_t size)
{
    assert(d_ptr != nullptr);
    assert(sizeInBytes == size);
    CUDA_CHECK(cudaMemcpy(d_ptr, (void *)t, size, cudaMemcpyHostToDevice));
}

void CudaBuffer::download(void *t, size_t size)
{
    assert(d_ptr != nullptr);
    assert(sizeInBytes == size);
    CUDA_CHECK(cudaMemcpy((void *)t, d_ptr, size, cudaMemcpyDeviceToHost));
}

void CudaBuffer::copy(CudaBuffer &src)
{
    resize(src.sizeInBytes);
    CUDA_CHECK(cudaMemcpy((void *)d_ptr, (void *)src.d_pointer(), src.sizeInBytes,
                          cudaMemcpyDeviceToDevice));
}